#include <string.h>
#include "Define.h"
#include "MQTT/Params.h"
#include "Core/Logger.h"
#include "Core/Interface.h"
#include "MQTT/MQTTError.h"

static SystemInterface *gOriginPortfile = nullptr;
static SystemInterface  gAiotPortfile;

#define ADAPTER_MBEDTLS_ENABLED    1

typedef struct {
    /**
     * @brief 创建1个网络
     */
    void * (*createNet)(void);
    /**
     * @brief 配置1个网络会话的连接参数
     */
    int32_t (*setNetOption)(void *handle, NetOption option, void *data);
    /**
     * @brief 建立网络连接
     */
    int32_t (*netEstablish)(void *handle);
    /**
     * @brief 从指定的网络会话上读取
     */
    int32_t (*netRecv)(void *handle, uint8_t *buffer, uint32_t len,int32_t* readLen,uint32_t timeout,NetAddress* addr);
    /**
     * @brief 在指定的网络会话上发送
     */
    int32_t (*netSend)(void *handle, uint8_t *buffer, uint32_t len,int32_t* sendLen,uint32_t timeout,NetAddress *addr);
    /**
     * @brief 销毁网络
     */
    int32_t (*destroyNet)(void **handle);

} AiotSecurityNetwork;

#ifdef ADAPTER_MBEDTLS_ENABLED
#include "Security/mbedtls/ssl.h"
#include "Security/mbedtls/debug.h"
#include "Security/mbedtls/timing.h"
#include "Security/mbedtls/ctr_drbg.h"
#include "Security/mbedtls/platform.h"
#include "Security/mbedtls/net_sockets.h"

typedef struct {
    mbedtls_net_context          netCtx;
    mbedtls_ssl_context          sslCtx;
    mbedtls_ssl_config           sslConfig;
    mbedtls_timing_delay_context timerDelayCtx;
    mbedtls_x509_crt             serverCert;
} MbedtlsCred;

#endif

typedef struct {
    void*                 networkHandle;
    SocketType            socketType;
    AiotCredInfo*         cred;
    char*                 host;
    uint16_t              port;
    uint32_t              connectTimeout;
#ifdef ADAPTER_MBEDTLS_ENABLED
    MbedtlsCred           mbedtls;
#endif
} SecurityNetwork;

#ifdef ADAPTER_MBEDTLS_ENABLED
#define MBEDTLS_MEM_INFO_MAGIC  (0x12345678)

static uint32_t gMbedtlsTotalMemUsed = 0;
static uint32_t MbedtlsMaxMemUsed = 0;

typedef struct {
    int32_t magic;
    int32_t size;
} MbedtlsMemInfo;


static uint8_t isHostIP(char *host) {

    uint32_t idx = 0;
    if (strlen(host) >= 16) {
        return 0;
    }

    for (idx = 0; idx < strlen(host); idx++) {
        if ((host[idx] != '.') && (host[idx] < '0' || host[idx] > '9')) {
            return 0;
        }
    }

    return 1;
}

static void *mbedtlsCalloc(size_t n, size_t size) {

    uint8_t *buf = nullptr;
    MbedtlsMemInfo *memInfo = nullptr;

    if (n == 0 || size == 0) {
        return nullptr;
    }

    buf = (uint8_t *)gOriginPortfile->memMalloc(n * size + sizeof(MbedtlsMemInfo));
    if (nullptr == buf) {
        loggerOut(aiotTrace,__FILE__,__LINE__,"malloc %d:%d failed\n",n,size);
        return nullptr;
    } else {
        memset(buf, 0, n * size + sizeof(MbedtlsMemInfo));
    }

    memInfo = (MbedtlsMemInfo *)buf;
    memInfo->magic = MBEDTLS_MEM_INFO_MAGIC;
    memInfo->size = n * size;
    buf += sizeof(MbedtlsMemInfo);

    gMbedtlsTotalMemUsed += memInfo->size;
    if (gMbedtlsTotalMemUsed > MbedtlsMaxMemUsed) {
        MbedtlsMaxMemUsed = gMbedtlsTotalMemUsed;
    }

    return buf;
}

static void mbedtlsFree(void *ptr) {

    MbedtlsMemInfo *memInfo = nullptr;
    if (nullptr == ptr) {
        return;
    }

    memInfo = (MbedtlsMemInfo *)((uint8_t *)ptr - sizeof(MbedtlsMemInfo));
    if (memInfo->magic != MBEDTLS_MEM_INFO_MAGIC) {
        loggerOut(aiotTrace,__FILE__,__LINE__,"Warning - invalid mem info magic: %d\n", memInfo->magic);
        return;
    }

    gMbedtlsTotalMemUsed -= memInfo->size;
    gOriginPortfile->memFree(memInfo);
}

static int32_t mbedtlsRandom(void *handle, uint8_t *output, size_t outputLen) {

    gOriginPortfile->getRand((int8_t*)output, outputLen);
    return 0;
}

static void mbedtlsDebug(void *ctx, int32_t level, const char *file, int32_t line, const char *str) {

    ((void) level);
    loggerOut(aiotTrace,file,line,"%s", (char *)str);
}

static int32_t mbedtlsNetSend(void *ctx, const uint8_t *buf, size_t len) {

    int32_t sendLen = 0;
    void *networkHandle = ((mbedtls_net_context *) ctx)->handle;
    int32_t res = gOriginPortfile->netSend(networkHandle, (uint8_t *)buf, len,&sendLen,5000, nullptr);
    //loggerOut(aiotTrace, __FILE__, __LINE__, "mbedtlsNetSend res:%d, sendLen:%d, len:%d\n", res, sendLen, len);
    if (res != aiotSuccess || sendLen!=len) {
        return MBEDTLS_ERR_NET_SEND_FAILED;
    }

    return sendLen;
}

static int32_t mbedtlsNetRecv(void *ctx, uint8_t *buf, size_t len) {

    int32_t recvLen = 0;
    void *networkHandle = ((mbedtls_net_context *) ctx)->handle;
    int32_t ret = gOriginPortfile->netRecv(networkHandle, buf, len,&recvLen,5000, nullptr);
    if (ret != aiotSuccess) {
        return MBEDTLS_ERR_NET_RECV_FAILED;
    } else {
        return recvLen;
    }
}

static int32_t mbedtlsNetRecvTimeout(void *ctx, uint8_t *buf, size_t len, uint32_t timeout) {

    int32_t recvLen = 0;
    void *networkHandle = ((mbedtls_net_context *) ctx)->handle;
    int32_t ret = gOriginPortfile->netRecv(networkHandle, buf, len,&recvLen,timeout, nullptr);
    if (ret != aiotSuccess) {
        return (MBEDTLS_ERR_NET_RECV_FAILED);
    } else {
        return recvLen;
    }
}

uint64_t mbedtlsTimingGetTimer(struct mbedtls_timing_hr_time *val, int32_t reset) {

    uint64_t delta;
    uint64_t offset;
    uint64_t *hrTime = (uint64_t*)&val->opaque;

    offset = gOriginPortfile->getTimestamp();
    if (reset) {
        *hrTime = offset;
        return (0);
    }

    delta = offset - *hrTime;
    return (delta);
}

void mbedtlsTimingSetDelay(void *data, uint32_t intMs, uint32_t finMs) {

    mbedtls_timing_delay_context *ctx = (mbedtls_timing_delay_context *) data;

    ctx->int_ms = intMs;
    ctx->fin_ms = finMs;
    if (finMs != 0) {
        (void) mbedtlsTimingGetTimer(&ctx->timer, 1);
    }
}

int32_t tlsNetworkEstablish(void *handle) {

    SecurityNetwork *adapterHandle = (SecurityNetwork *)handle;
    int32_t res = 0;

    loggerOut(aiotInfo,__FILE__,__LINE__,"establish ssl connection with server(host='%s', port=[%d])\n",adapterHandle->host,adapterHandle->port);

    adapterHandle->mbedtls.netCtx.handle = adapterHandle->networkHandle;
    adapterHandle->mbedtls.netCtx.fd = 1;
    if (adapterHandle->cred->tlsFragment == 0) {
        loggerOut(aiotDebug,__FILE__,__LINE__,"invalid max tls fragment parameter\n");
        return tlsInvalidMaxFrangment;
    }

    if (adapterHandle->cred->tlsFragment <= 512) {
        res = mbedtls_ssl_conf_max_frag_len(&adapterHandle->mbedtls.sslConfig, MBEDTLS_SSL_MAX_FRAG_LEN_512);
    } else if (adapterHandle->cred->tlsFragment <= 1024) {
        res = mbedtls_ssl_conf_max_frag_len(&adapterHandle->mbedtls.sslConfig, MBEDTLS_SSL_MAX_FRAG_LEN_1024);
    } else if (adapterHandle->cred->tlsFragment <= 2048) {
        res = mbedtls_ssl_conf_max_frag_len(&adapterHandle->mbedtls.sslConfig, MBEDTLS_SSL_MAX_FRAG_LEN_2048);
    } else if (adapterHandle->cred->tlsFragment <= 4096) {
        res = mbedtls_ssl_conf_max_frag_len(&adapterHandle->mbedtls.sslConfig, MBEDTLS_SSL_MAX_FRAG_LEN_4096);
    } else {
        res = mbedtls_ssl_conf_max_frag_len(&adapterHandle->mbedtls.sslConfig, MBEDTLS_SSL_MAX_FRAG_LEN_NONE);
    }

    if (res < 0) {
        loggerOut(aiotTrace,__FILE__,__LINE__,"ssl conf max frag len error, res: %d\n", res);
        return tlsSetMaxFragmentFailed;
    }

    res = mbedtls_ssl_config_defaults(&adapterHandle->mbedtls.sslConfig, MBEDTLS_SSL_IS_CLIENT,MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT);
    if (res != 0) {
        loggerOut(aiotTrace,__FILE__,__LINE__,"ssl config defaults error, res: %d\n", res);
        return tlsSetConfigFailed;
    }

    /**服务签名只支持单向认证,客户端不验证服务器证书*/
    mbedtls_ssl_conf_authmode(&adapterHandle->mbedtls.sslConfig,MBEDTLS_SSL_VERIFY_OPTIONAL);
    mbedtls_ssl_conf_max_version(&adapterHandle->mbedtls.sslConfig, MBEDTLS_SSL_MAJOR_VERSION_3,MBEDTLS_SSL_MINOR_VERSION_3);
    mbedtls_ssl_conf_min_version(&adapterHandle->mbedtls.sslConfig, MBEDTLS_SSL_MAJOR_VERSION_3,MBEDTLS_SSL_MINOR_VERSION_3);
    mbedtls_ssl_conf_handshake_timeout(&adapterHandle->mbedtls.sslConfig, (MBEDTLS_SSL_DTLS_TIMEOUT_DFL_MIN * 2),(MBEDTLS_SSL_DTLS_TIMEOUT_DFL_MIN * 2 * 4));
    mbedtls_ssl_conf_rng(&adapterHandle->mbedtls.sslConfig, mbedtlsRandom, nullptr);
    mbedtls_ssl_conf_dbg(&adapterHandle->mbedtls.sslConfig, mbedtlsDebug, stdout);

    if (adapterHandle->cred->option == aiotCredFile) {

        if (adapterHandle->cred->credFile == nullptr && adapterHandle->cred->credLength == 0) {
            loggerOut(aiotDebug,__FILE__,__LINE__,"invalid x509 server cert\n");
            return tlsInvalidServerCert;
        }

        mbedtls_x509_crt_init(&adapterHandle->mbedtls.serverCert);
        res = mbedtls_x509_crt_parse(&adapterHandle->mbedtls.serverCert,
                                     (const uint8_t *)adapterHandle->cred->credFile,(size_t)adapterHandle->cred->credLength + 1);
        if (res < 0) {
            loggerOut(aiotTrace,__FILE__,__LINE__,"x509 crt parse server cert error, res: %d\n",res);
            return tlsInvalidServerCert;
        }

        mbedtls_ssl_conf_ca_chain(&adapterHandle->mbedtls.sslConfig, &adapterHandle->mbedtls.serverCert, nullptr);
    } else {
        loggerOut(aiotDebug,__FILE__,__LINE__,"unsupported security option\n");
        return tlsInvalidCredOption;
    }

    res = mbedtls_ssl_setup(&adapterHandle->mbedtls.sslCtx, &adapterHandle->mbedtls.sslConfig);
    if (res < 0) {
        loggerOut(aiotTrace,__FILE__,__LINE__,"ssl setup error, res: %d\n",res);
        return tlsSetupFailed;
    }

    /**主机地址 非ip 加入到ssl ctx中*/
    if (isHostIP(adapterHandle->host) == 0) {
        res = mbedtls_ssl_set_hostname(&adapterHandle->mbedtls.sslCtx, adapterHandle->host);
        if (res < 0) {
            loggerOut(aiotTrace,__FILE__,__LINE__,"ssl set hostname error, res: %d\n",res);
            return tlsSetHostnameFailed;
        }
    }

     mbedtls_ssl_set_bio(&adapterHandle->mbedtls.sslCtx, &adapterHandle->mbedtls.netCtx, mbedtlsNetSend,mbedtlsNetRecv, mbedtlsNetRecvTimeout);
    
    mbedtls_ssl_conf_read_timeout(&adapterHandle->mbedtls.sslConfig, adapterHandle->connectTimeout);

    while ((res = mbedtls_ssl_handshake(&adapterHandle->mbedtls.sslCtx)) != 0) {
        if ((res != MBEDTLS_ERR_SSL_WANT_READ) && (res != MBEDTLS_ERR_SSL_WANT_WRITE)) {
            loggerOut(aiotTrace,__FILE__,__LINE__,"ssl handshake error, ret: %d\n", res);
            if (res == MBEDTLS_ERR_SSL_INVALID_RECORD) {
                res = tlsSocketInvalid;
            } else {
                res = tlsInvalidHandshake;
            }

            return res;
        }
    }

    res = mbedtls_ssl_get_verify_result(&adapterHandle->mbedtls.sslCtx);
    if (res == MBEDTLS_X509_BADCERT_NOT_TRUSTED) {
        char vrfyBuf[128] = {0};
        mbedtls_x509_crt_verify_info(vrfyBuf,sizeof(vrfyBuf), "!",res);
        loggerOut(aiotWarning,__FILE__,__LINE__,"ssl verify result error,%s\n",vrfyBuf);
    } else if (res != 0) {
        char vrfyBuf[128] = {0};
        mbedtls_x509_crt_verify_info(vrfyBuf,sizeof(vrfyBuf), "!",res);
        loggerOut(aiotError,__FILE__,__LINE__,"ssl verify result %d,info %s\n",vrfyBuf,vrfyBuf);
        return tlsGetVerifyResultFailed;
    }

    loggerOut(aiotInfo,__FILE__,__LINE__,"ssl establish connection success,cost %d bytes in total, max used %d bytes)\n",gMbedtlsTotalMemUsed,MbedtlsMaxMemUsed);
    return aiotSuccess;
}

int32_t tlsNetworkRecv(void *handle, uint8_t *buffer, uint32_t len, int32_t* readLen,uint32_t timeout, NetAddress *addr) {

    int32_t res = 0;
    int32_t recvBytes = 0;
    SecurityNetwork *adapterHandle = (SecurityNetwork *)handle;
    if (handle == nullptr) {
        return paramsIsNull;
    }

    mbedtlsTimingSetDelay(&adapterHandle->mbedtls.timerDelayCtx, 0, 0);
    mbedtls_ssl_conf_read_timeout(&adapterHandle->mbedtls.sslConfig, timeout);

    do {
        res = mbedtls_ssl_read(&adapterHandle->mbedtls.sslCtx, buffer + recvBytes, len - recvBytes);
        if (res < 0) {
            if (res == MBEDTLS_ERR_SSL_TIMEOUT) {
                break;
            } else if (res != MBEDTLS_ERR_SSL_WANT_READ && res != MBEDTLS_ERR_SSL_WANT_WRITE && res != MBEDTLS_ERR_SSL_CLIENT_RECONNECT) {

                if (recvBytes == 0) {
                    loggerOut(aiotTrace,__FILE__,__LINE__,"ssl recv error, res: %d\n",res);
                    if (res == MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY) {
                        return tlsRecvConnectionClosed;
                    } else if (res == MBEDTLS_ERR_SSL_INVALID_RECORD) {
                        return tlsSocketInvalid;
                    } else {
                        return tlsRecvFailed;
                    }
                }

                break;
            }
        } else if (res == 0) {
            break;
        } else {
            recvBytes += res;
        }

    } while (recvBytes < len);

    *readLen = recvBytes;
    return aiotSuccess;
}

int32_t tlsNetworkSend(void *handle, uint8_t *buffer, uint32_t len, int32_t *sendLen, uint32_t timeout, NetAddress *addr) {

    int32_t res = 0;
    int32_t sendBytes = 0;
    uint64_t timeStart = 0, timenow = 0;
    SecurityNetwork *adapterHandle = (SecurityNetwork *)handle;
    if (handle == nullptr) {
        return paramsIsNull;
    }

    /** start time */
    timeStart = gOriginPortfile->getTimestamp();

    do {
        //loggerOut(aiotTrace,__FILE__,__LINE__,"1============mbedtls_ssl_write len\n");
        timenow = gOriginPortfile->getTimestamp();
        if (timenow - timeStart >= timenow || timeout - (timenow - timeStart) > timeout) {
            break;
        }

        res = mbedtls_ssl_write(&adapterHandle->mbedtls.sslCtx, buffer + sendBytes, len - sendBytes);
        //loggerOut(aiotTrace,__FILE__,__LINE__,"2============mbedtls_ssl_write len res:%d remain:%d\n", res, len - sendBytes);
        if (res < 0) {
            if (res != MBEDTLS_ERR_SSL_WANT_READ && res != MBEDTLS_ERR_SSL_WANT_WRITE) {
                if (sendBytes == 0) {
                    loggerOut(aiotTrace,__FILE__,__LINE__,"ssl send error, res: %d\n",res);
                    if (res == MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY) {
                        return tlsSendConnectionClosed;
                    } else if (res == MBEDTLS_ERR_SSL_INVALID_RECORD) {
                        return tlsSocketInvalid;
                    } else {
                        return tlsSendFailed;
                    }
                }

                break;
            }
        } else if (res == 0) {
            break;
        } else {
            sendBytes += res;
        }

    } while (((timenow - timeStart) < timeout) && (sendBytes < len));

    *sendLen = sendBytes;
    //loggerOut(aiotTrace,__FILE__,__LINE__,"mbedtls_ssl_write len: %d, sendLen:%d\n",len, *sendLen);
    return aiotSuccess;
}
#endif

void * adapterNetworkInit(void) {

    SecurityNetwork *adapterHandle = nullptr;

    adapterHandle = gOriginPortfile->memMalloc(sizeof(SecurityNetwork));
    if (adapterHandle == nullptr) {
        return nullptr;
    }

    memset(adapterHandle, 0, sizeof(SecurityNetwork));
    adapterHandle->networkHandle = gOriginPortfile->createNet();
#ifdef ADAPTER_MBEDTLS_ENABLED

    mbedtls_debug_set_threshold(0);
    mbedtls_ssl_init(&adapterHandle->mbedtls.sslCtx);
    mbedtls_ssl_config_init(&adapterHandle->mbedtls.sslConfig);
    mbedtls_platform_set_calloc_free(mbedtlsCalloc, mbedtlsFree);
    gMbedtlsTotalMemUsed = MbedtlsMaxMemUsed = 0;
#endif

    return adapterHandle;
}

int32_t adapterNetworkSetopt(void *handle, NetOption option, void *data) {

    int32_t res = aiotSuccess;
    SecurityNetwork *adapterHandle = (SecurityNetwork *)handle;
    if (handle == nullptr || data == nullptr) {
        return paramsIsNull;
    }

    res = gOriginPortfile->setNetOption(adapterHandle->networkHandle, option, data);

#ifdef ADAPTER_MBEDTLS_ENABLED
    switch (option) {
        case socketType: {
            adapterHandle->socketType = tcpClient;
        }
            break;
        case netHost: {
            adapterHandle->host = gOriginPortfile->memMalloc(strlen(data) + 1);
            if (adapterHandle->host == nullptr) {
                loggerOut(aiotDebug,__FILE__,__LINE__,"malloc failed\n");
                return memoryMallocFailed;
            }

            memset(adapterHandle->host, 0, strlen(data) + 1);
            memcpy(adapterHandle->host, data, strlen(data));
        }
            break;
        case netPort: {
            adapterHandle->port = *(uint16_t *)data;
        }
            break;
        case connectTimeout: {
            adapterHandle->connectTimeout = *(uint32_t *)data;
        }
            break;

        case networkCred: {
            adapterHandle->cred = gOriginPortfile->memMalloc(sizeof(AiotCredInfo));
            if (adapterHandle->cred == nullptr) {
                loggerOut(aiotDebug,__FILE__,__LINE__,"malloc failed\n");
                return memoryMallocFailed;
            }

            memset(adapterHandle->cred, 0, sizeof(AiotCredInfo));
            memcpy(adapterHandle->cred, data, sizeof(AiotCredInfo));
        }
            break;

        default: {
            loggerOut(aiotTrace,__FILE__,__LINE__,"unknown option %d\n", option);
        }
            break;
    }
#endif

    return res;
}

int32_t adapterNetworkEstablish(void *handle) {

    SecurityNetwork *adapterHandle = (SecurityNetwork *)handle;
    if (handle == nullptr) {
        return paramsIsNull;
    }

    int32_t res = gOriginPortfile->netEstablish(adapterHandle->networkHandle);
    if (res != aiotSuccess) {
        return res;
    }

#ifdef ADAPTER_MBEDTLS_ENABLED
    if (adapterHandle->cred != nullptr && adapterHandle->cred->option != aiotCredNone) {
        res = tlsNetworkEstablish(adapterHandle);
    }
#endif

    return res;
}

int32_t adapterNetworkRecv(void *handle, uint8_t *buffer, uint32_t len, int32_t *readLen, uint32_t timeout, NetAddress *addr) {

    int32_t res = aiotSuccess;
    SecurityNetwork *adapterHandle = (SecurityNetwork *)handle;
    if (handle == nullptr) {
        return paramsIsNull;
    }

#ifdef ADAPTER_MBEDTLS_ENABLED
    if (adapterHandle->cred != nullptr && adapterHandle->cred->option != aiotCredNone) {
        res = tlsNetworkRecv(handle, buffer, len,readLen,timeout, addr);
    } else
#endif
    {
        res = gOriginPortfile->netRecv(adapterHandle->networkHandle, buffer, len,readLen,timeout,addr);
    }

    return res;
}

int32_t adapterNetworkSend(void *handle, uint8_t *buffer, uint32_t len, int32_t *sendLen, uint32_t timeout, NetAddress *addr) {

    int32_t res = aiotSuccess;
    SecurityNetwork *adapterHandle = (SecurityNetwork *)handle;
    if (handle == nullptr) {
        return paramsIsNull;
    }
#ifdef ADAPTER_MBEDTLS_ENABLED
    if (adapterHandle->cred != nullptr && adapterHandle->cred->option != aiotCredNone) {
        res = tlsNetworkSend(handle, buffer, len,sendLen,timeout, addr);
    } else
#endif
    {
        res = gOriginPortfile->netSend(adapterHandle->networkHandle, buffer, len,sendLen,timeout, addr);
    }

    return res;
}

int32_t adapterNetworkDeinit(void **handle) {

    SecurityNetwork *adapterHandle = nullptr;
    if (handle == nullptr || *handle == nullptr) {
        return paramsIsNull;
    }

    adapterHandle = *(SecurityNetwork **)handle;

    if (adapterHandle->host != nullptr) {
        gOriginPortfile->memFree(adapterHandle->host);
        adapterHandle->host = nullptr;
    }

#ifdef ADAPTER_MBEDTLS_ENABLED

    mbedtls_ssl_close_notify(&adapterHandle->mbedtls.sslCtx);
    if (adapterHandle->cred != nullptr && adapterHandle->cred->option == aiotCredFile) {
        mbedtls_x509_crt_free(&adapterHandle->mbedtls.serverCert);
    }

    mbedtls_ssl_free(&adapterHandle->mbedtls.sslCtx);
    mbedtls_ssl_config_free(&adapterHandle->mbedtls.sslConfig);

    gMbedtlsTotalMemUsed = MbedtlsMaxMemUsed = 0;

#endif
    if (adapterHandle->cred != nullptr) {
        gOriginPortfile->memFree(adapterHandle->cred);
        adapterHandle->cred = nullptr;
    }

    loggerOut(aiotDebug,__FILE__,__LINE__,"adapter network destroy\n");
    gOriginPortfile->destroyNet(&adapterHandle->networkHandle);
    gOriginPortfile->memFree(adapterHandle);
    *handle = nullptr;

    return aiotSuccess;
}

static AiotSecurityNetwork adapterNetwork = {
    adapterNetworkInit,
    adapterNetworkSetopt,
    adapterNetworkEstablish,
    adapterNetworkRecv,
    adapterNetworkSend,
    adapterNetworkDeinit,
};

SystemInterface *getAiotAdapterNet(SystemInterface *portfile) {

    if (portfile == nullptr) {
        return nullptr;
    }

    gOriginPortfile = portfile;
    gAiotPortfile = *portfile;
    gAiotPortfile.createNet = adapterNetwork.createNet;
    gAiotPortfile.setNetOption = adapterNetwork.setNetOption;
    gAiotPortfile.netEstablish = adapterNetwork.netEstablish;
    gAiotPortfile.netRecv = adapterNetwork.netRecv;
    gAiotPortfile.netSend = adapterNetwork.netSend;
    gAiotPortfile.destroyNet = adapterNetwork.destroyNet;
    return &gAiotPortfile;
}